#include "Alice/Systems/OBBSys.h"
#include "Alice/Components/OBBComp.hpp"
#include "Alice/Components/TransformComp.hpp"
#include "Alice/Core/World.h"
#include "Alice/Math/OBBRect.h"
#include "Alice/Systems/VisualBoxSys.h"

namespace Alice
{

void OBBSys::OnUpdate()
{
    for (auto entity : entitys)
    {
		TransformComp& a_tf_comp = world->GetComp<TransformComp>(entity);
        OBBComp& a_obb_comp = world->GetComp<OBBComp>(entity);

		for (auto other_entity : entitys)
        {
            if (other_entity == entity)
                continue;
		
			TransformComp& b_tf_comp = world->GetComp<TransformComp>(other_entity);
            OBBComp& b_obb_comp = world->GetComp<OBBComp>(other_entity);

			if (IsCollision(a_obb_comp, b_obb_comp, a_tf_comp, b_tf_comp))
            {
                // 使用实体 ID 作为事件 ID 发送一个 OBB 碰撞事件
                Event collision_event(COLLISION(entity));
                collision_event.SetParam<Entity>("self", entity);
                collision_event.SetParam<Entity>("other", other_entity);
                world->GetEventMngr()->SendEvent(collision_event);
                world->GetSys<VisualBoxSys>()
                    ->GetShader().Use().SetVec3f("BoxColor", 1.0f, 0.0f, 0.0f);
            }
            else
            {
                world->GetSys<VisualBoxSys>()
                    ->GetShader().Use().SetVec3f("BoxColor", 0.94f, 0.94f, 1.0f);
            }
		}
    }
}

bool OBBSys::IsCollision(OBBComp& a, OBBComp& b, TransformComp& a_tf, TransformComp& b_tf)
{
	OBBRect a_obb{
		Vec2{a_tf.position.x, a_tf.position.y},
		Vec2{a_tf.position.x + a.width, a_tf.position.y},
		Vec2{a_tf.position.x + a.width, a_tf.position.y + a.height},
		Vec2{a_tf.position.x, a_tf.position.y + a.height}
	};
	OBBRect b_obb{
		Vec2{b_tf.position.x, b_tf.position.y},
		Vec2{b_tf.position.x + b.width, b_tf.position.y},
		Vec2{b_tf.position.x + b.width, b_tf.position.y + b.height},
		Vec2{b_tf.position.x, b_tf.position.y + b.height}
	};

    Vec2 a_center{
        a_tf.position.x + a.width / 2,
        a_tf.position.y + a.height / 2
    };
    Vec2 b_center{
        b_tf.position.x + b.width / 2,
        b_tf.position.y + b.height / 2
    };

    a_obb = OBBRect::CalRotateRect(a_obb, a_center, a_tf.rotate);
    b_obb = OBBRect::CalRotateRect(b_obb, b_center, b_tf.rotate);

    float min_overlap = std::numeric_limits<float>::infinity();
    // 得到四条分离轴
    std::array<Vec2, 4> axes = OBBRect::CalRectAxes(a_obb, b_obb);
    for (auto& axis : axes)
    {
        Vec2 a_proj = OBBRect::CalProjOnAxis(a_obb, axis);
        Vec2 b_proj = OBBRect::CalProjOnAxis(b_obb, axis);
    
        float overlap = Vec2::CalOverlappLength(a_proj, b_proj);
        if (overlap == 0.0f)
        {
            return false;
        }
        else
        {
            if (overlap < min_overlap)
                min_overlap = overlap;
        }
    }

    return true;
}

} // namespace Alice

